package com.llp.view.opengl;

import android.opengl.GLES20;
import android.util.Log;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;

public class TriangleShapeRender extends BaseShapeRender {
    private static final String TAG = "TriangleShapeRender";
    /**
     * 整个GLES2.0的使用步骤：
     * 1.定义顶点着色器vertexShader+片元着色器fragmentShader
     * 定义shader有一套专门的语言--GLSL语言，具体语言学习可以参考https://www.cnblogs.com/kex1n/p/3941680.html
     * 2.确定绘制的顶点以及颜色， 具体坐标位置学习可以参数https://blog.csdn.net/junzia/article/details/52801772
     * 3.初始化program并连上顶点以及片元着色器，连接program-->onSurfaceCreated
     * 4.设置view的窗口-->onSurfaceChanged
     * 5.绘制-->onDrawFrame
     */

    //step1+++
    private final String VertexShaderCode =
            "attribute vec4 vPosition;" + //定义一个vPosition参数,该参数代表绘制的顶点
                    "void main() {" +
                    "  gl_Position = vPosition;" + //将vPosition赋值给glsl内部变量gl_Position.
                    "}";
    private final String FragmentShaderCode =
            "uniform vec4 vColor;" +  //定义一个vColor参数,该参数代表片元着色器绘制的颜色
                    "void main() {" +
                    "  gl_FragColor = vColor;" + //将vColor赋值给glsl内部变量gl_FragColor.
                    "}";
    private int mVertexShader;
    private int mFragmentShader;
    //step1---

    //step2+++
    private static final int COORDS_PER_VERTEX = 3; //固定值, 因为openGL绘制都是由点、线、三角形组成
    static float triangleCoords[] = { //三角形的顶点坐标
            0.0f, 0.5f, 0.0f, // top
            -0.5f, 0.0f, 0.0f, // bottom left
            0.5f, 0.0f, 0.0f  // bottom right
    };
    /**
     * 由于OpenGL是很底层的画图接口，其使用的数据缓冲结构和Java层所使用的不一样。
     * (Java保存字节为高位在前，低位在后； 而OpenGl是低位在前，高位在后)
     * 因此我们需要将在Java层所定义的float[]进行一定的转换方可传给OpenGl来进行使用
     */
    private FloatBuffer mVertexBuffer; //将顶点转为buffer并传给GLES
    //设置颜色，依次为红绿蓝和透明通道
    static float color[] = {1.0f, 1.0f, 1.0f, 1.0f}; //color可以直接作为数组转给GLES,无需像顶点坐标转化
    //step2---

    //step3+++
    private int mProgram;
    private int mPositionHandle;
    private int mColorHandle;
    private final int mVertexCount = triangleCoords.length / COORDS_PER_VERTEX; //顶点的个数
    private final int mVertexStride = COORDS_PER_VERTEX * 4; // 顶点的偏移量，每个顶点占四个字节
    //step3---

    public TriangleShapeRender() {
        super();
        init();
    }

    private void init() {
        Log.i(TAG, "init shader");
        //step1.初始化VertexBuffer
        ByteBuffer byteBuffer = ByteBuffer.allocateDirect(
                triangleCoords.length * 4); //定义一个指定大小的buffer, 一个float占4个字节
        byteBuffer.order(ByteOrder.nativeOrder()); //将该buffer的排序位置和系统的排序位置保持一直： 1. 低位在前; 2. 高位在前
        mVertexBuffer = byteBuffer.asFloatBuffer();
        mVertexBuffer.put(triangleCoords);
        //创建一个长度为length的FloatBuffer时候,
        //如果存储方式为opengl的存储方式，在每次调用put加入点后position都会加1，因此加入点后在绘图时候将position重置为0
        mVertexBuffer.position(0);
    }

    @Override
    public void onSurfaceCreated(GL10 gl, EGLConfig config) {
        //step1+. 初始化shader
        mVertexShader = loadShader(GLES20.GL_VERTEX_SHADER,
                VertexShaderCode);
        mFragmentShader = loadShader(GLES20.GL_FRAGMENT_SHADER,
                FragmentShaderCode);
        ////step3. 初始化program,并连上着色器程序
        GLES20.glClearColor(0.5f, 0.5f, 0.5f, 1.0f);
        init();
        Log.i(TAG, "onSurfaceCreated, program should be initialed in this time");
        mProgram = GLES20.glCreateProgram(); //创建一个空的program
        GLES20.glAttachShader(mProgram, mVertexShader); //连上顶点着色器
        GLES20.glAttachShader(mProgram, mFragmentShader); //连上片元着色器
        GLES20.glLinkProgram(mProgram); //连接program
    }

    @Override
    public void onSurfaceChanged(GL10 gl, int width, int height) { //step4
        GLES20.glViewport(0, 0, width, height); //设置GLES的窗口
    }

    @Override
    public void onDrawFrame(GL10 gl) { //step5
        GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
        Log.i(TAG, "onDrawFrame, application should be contacted with GLES");
        GLES20.glUseProgram(mProgram); //将程序加入gles环境中
        mPositionHandle = GLES20.glGetAttribLocation(mProgram, "vPosition"); //拿到nPosition参数的地址
        GLES20.glEnableVertexAttribArray(mPositionHandle); //设置该地址可操作
        GLES20.glVertexAttribPointer(mPositionHandle, COORDS_PER_VERTEX, GLES20.GL_FLOAT,
                false, mVertexStride, mVertexBuffer); //设置顶点着色器参数到gles

        mColorHandle = GLES20.glGetUniformLocation(mProgram, "vColor"); //拿到vColor参数的地址
        GLES20.glUniform4fv(mColorHandle, 1, color, 0); //设置片元着色器颜色到gles

        GLES20.glDrawArrays(GLES20.GL_TRIANGLES, 0, mVertexCount); //绘制
        //GLES20.glDisableVertexAttribArray(mPositionHandle);
    }
}
